﻿using System;
using System.Collections.Generic;
using CompactMapper.Orm.UnitOfWork.Commands.Interfaces;
using CompactMapper.Orm.UnitOfWork.Mappings.Meta.PropertyInfos.Relations;
using CompactMapper.Orm.UnitOfWork.Mappings.Meta.Table;

namespace CompactMapper.Orm.UnitOfWork.Mappings
{
    internal class Table : IEquatable<Table>
    {
        private readonly Dictionary<String, Relationship> _relationshipsByParentTableName = new Dictionary<String, Relationship>();

        private readonly TableMetaInfo _meta;

        public ICreateTableCommand CreateTableCommand;
        public IDeleteCommand DeleteCommand;
        public IInsertCommand InsertCommand;
        public IQueryCommand QueryCommand;
        public IGetByKeyCommand GetByKeyCommand;

        public Table(Type tableType)
        {
            _meta = new TableMetaInfo(tableType);
        }

        public virtual Boolean AlreadyCreated { get; set; }

        public IEnumerable<Relationship> Relationships
        {
            get { return _relationshipsByParentTableName.Values; }
        }

        public string Name
        {
            get { return Meta.Name; }
        }

        public TableMetaInfo Meta
        {
            get { return _meta; }
        }


        public bool Equals(Table other)
        {
            return Name.Equals(other.Name);
        }

        public Relationship GetRelationshipWith(String parentTableName)
        {
            if (!String.IsNullOrEmpty(parentTableName) && _relationshipsByParentTableName.ContainsKey(parentTableName))
            {
                return _relationshipsByParentTableName[parentTableName];
            }
            return Relationship.None;
        }


        public Relation GetRelationshipAttribute(String dependantTableName)
        {
            return Meta.RelationsByTableName[dependantTableName];
        }

        public void AddRelationship(Table parentTable)
        {
            var parentTableName = parentTable.Name;
            var relationAttribute = parentTable.GetRelationshipAttribute(Meta.Name);

            if (_relationshipsByParentTableName.ContainsKey(parentTableName))
                return;
            var relation = Relationship.Create(relationAttribute, parentTableName);
            _relationshipsByParentTableName.Add(parentTableName, relation);
        }

        // override object.Equals
        public override bool Equals(object obj)
        {
            //       
            // See the full list of guidelines at
            //   http://go.microsoft.com/fwlink/?LinkID=85237  
            // and also the guidance for operator== at
            //   http://go.microsoft.com/fwlink/?LinkId=85238
            //

            if (obj == null || GetType() != obj.GetType())
            {
                return false;
            }
            return Equals((Table)obj);
        }

        // override object.GetHashCode
        public override int GetHashCode()
        {
            return Name.GetHashCode();
        }

        public override string ToString()
        {
            return Name;
        }
    }
}